package br.unifor.cct.mia.xover;

import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.evolutionary.Individual;
import br.unifor.cct.mia.ga.Ga;
import br.unifor.cct.mia.util.Methods;

public class BasicXOver extends XOver {

	private void xover(Ga Ga) {
        if (Ga.configurations.getNvars() > 1) {
            int point = (Ga.configurations.getNvars() == 2?1:Methods.randIntValue(1, Ga.configurations.getNvars()));
            int rest = Ga.configurations.getNvars() - point;
            
            //double aux[] = new double[point];
            double aux2[] = new double[Ga.configurations.getNvars()];
            
            //System.arraycopy(((Genotype)Ga.population[one]).getGene(), 0, aux, 0, point-1);
            //System.arraycopy(((Genotype)Ga.population[two]).getGene(), 0, aux, point, rest);
            
            System.arraycopy(((Genotype)Ga.population[one]).getGene(), point, aux2, point, rest);
            System.arraycopy(((Genotype)Ga.population[two]).getGene(), 0, aux2, 0, point-1);
                        
            /*System.arraycopy(aux, 0, ((Genotype)Ga.population[two]).getGene(), 0, point-1);
            System.arraycopy(aux2, 0, ((Genotype)Ga.population[one]).getGene(), point, rest);*/
            
            //Troca pelo pior
            Genotype filho = new Genotype(Ga.configurations);        	       	
            filho.setFitness(0);
            filho.setSelectProbability(0);   
            filho.setGene(aux2);
            
            replaceWorst(Ga,filho);
        }
	}
	
	private void replaceWorst(Ga ga, Genotype filho ) {
		Individual[] population = ga.population;
		 
		int minPos = 0;
		double minVal = Integer.MAX_VALUE;
		for ( int i=1; i<ga.configurations.getPopsize(); i++ ) {			
			if ( population[i].fitness>=0 && population[i].fitness<minVal ) {
				minPos = i;
				minVal = population[i].fitness;
			}			
		}		
		
		System.arraycopy(filho.getGene(), 0, ((Genotype)population[minPos]).getGene(), 0, filho.getGene().length);
		population[minPos].setFitness(-1);
	}
	
	public Object execute(Object value) {
    	Object[] o = (Object[])value;
		Ga Ga = (Ga)o[0];
		
		xover(Ga);
		return Ga.population;
	}
}